package cn.jingyuan.fox.support.config;

import cn.jingyuan.fox.support.thread.enhance.EnhancedLogThreadPoolExecutor;
import cn.jingyuan.fox.support.thread.handler.SimpleUncaughtExceptionHandler;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池配置
 */
@Configuration
public class ExecutorServiceConfig implements InitializingBean {

    public static final String executorServiceName = "default-executor-service";

    /**
     * 定义 & 配置线程池
     */
    @Bean(name = executorServiceName, destroyMethod = "shutdown")
    public ExecutorService defaultExecutorService() {
        int threadPoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
        int corePoolSize = threadPoolSize / 2;

        ThreadPoolExecutor executor = new EnhancedLogThreadPoolExecutor(
            corePoolSize,
            threadPoolSize,
            1,
            TimeUnit.MINUTES,
            new LinkedBlockingQueue<>(500),
            new ThreadFactoryBuilder()
                .setNameFormat(executorServiceName + "-%d")
                .setDaemon(true)
                .setUncaughtExceptionHandler(new SimpleUncaughtExceptionHandler())
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy()
        );

        executor
            .allowCoreThreadTimeOut(true);

        return executor;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (Thread.getDefaultUncaughtExceptionHandler() != null) {
            Thread.setDefaultUncaughtExceptionHandler(new SimpleUncaughtExceptionHandler());
        }
    }

}
